package com.xyoto.takeawayUser.service.impl;

import com.xyoto.takeawayUser.constant.DataBasesOperationResult;
import com.xyoto.takeawayUser.constant.UserAddrConstant;
import com.xyoto.takeawayUser.dto.SaveUserAddrDTO;
import com.xyoto.takeawayUser.dto.UpdateUserAddrDTO;
import com.xyoto.takeawayUser.dto.UpdateUserDTO;
import com.xyoto.takeawayUser.entity.UserAddr;
import com.xyoto.takeawayUser.entity.UserCache;
import com.xyoto.takeawayUser.enums.UserEnum;
import com.xyoto.takeawayUser.enums.WechatLoginEnum;
import com.xyoto.takeawayUser.exception.ExceptionUtils;
import com.xyoto.takeawayUser.mapper.UserAddrMapper;
import com.xyoto.takeawayUser.mapper.UserMapper;
import com.xyoto.takeawayUser.po.UpdateUserPO;
import com.xyoto.takeawayUser.service.UserService;
import com.xyoto.takeawayUser.utils.RedisUtils;
import com.xyoto.takeawayUser.utils.Result;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Service
@Slf4j
public class UserServiceImpl implements UserService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RedisUtils redisUtils;

    @Autowired
    private HttpServletRequest request;

    @Autowired
    private UserAddrMapper userAddrMapper;

    /**
     * 通过用户id获取用户详情
     * @return
     */
    @Override
    public Result getUserById() {
        log.info("查询用户信息");
        UserCache redisUserMessage = redisUtils.getRedisUserMessage(request);
        if (redisUserMessage == null){
            ExceptionUtils.error(UserEnum.GET_USER_FAILED);
        }
        return Result.success(redisUserMessage);
    }

    /**
     * 修改用户信息
     * @param updateUserDTO
     * @return
     */
    @Override
    public Result updateUserInfo(UpdateUserDTO updateUserDTO) {
        log.info("开始修改个人信息");
        boolean flag = redisUtils.checkTokenStatus(request);
        if (!flag){
            log.info("修改个人信息失败");
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }

        if ("".equals(updateUserDTO.getNickname())){
            return Result.error("输入昵称错误，请重试");
        }

        UserCache redisUserMessage = redisUtils.getRedisUserMessage(request);
        int userId = redisUserMessage.getId();
        UpdateUserPO userPO = new UpdateUserPO();
        userPO.setId(userId);
        userPO.setNickname(updateUserDTO.getNickname());

        Integer i = userMapper.updateUserInfo(userPO);
        if (i == null){
            log.info("修改个人信息失败");
            ExceptionUtils.error(UserEnum.USER_UPDATE_INFO_FAILED);
        }
        log.info("修改个人信息成功");
        return Result.success("修改成功");
    }

    /**
     * 保存用户地址
     * @param saveUserAddrDTO 保存地址实体
     * @return
     */
    @Override
    @Transactional
    public Result saveAddr(SaveUserAddrDTO saveUserAddrDTO) {

        UserCache userCache = redisUtils.getRedisUserMessage(request);
        Integer userId = userCache.getId();
        UserAddr userAddr = new UserAddr();
        BeanUtils.copyProperties(saveUserAddrDTO, userAddr);
        //查询是否已有地址，若无则添加为默认地址
        Integer addrNum = userAddrMapper.getAddrNum(userId);
        if (addrNum < UserAddrConstant.ADDRESS_NUM){
            userAddr.setDefaultAddr(UserAddrConstant.DEFAULT_STATE_TRUE);
        }
        userAddr.setUserId(userId);

        //查询是否已有默认地址
        isDefaultAddr(saveUserAddrDTO.getDefaultAddr(), userId);

        log.info("新增用户地址");
        Integer addNum = userAddrMapper.saveUserAddr(userAddr);
        if (addNum == DataBasesOperationResult.ERROR){
            log.info("新增用户地址失败");
            ExceptionUtils.error(UserEnum.SAVE_USER_ERROR);
        }

        return Result.success();
    }

    /**
     * 修改我的地址
     * @param updateUserAddrDTO 修改我的地址实体类
     * @return
     */
    @Override
    public Result updateUserAddr(UpdateUserAddrDTO updateUserAddrDTO) {

        UserCache userCache = redisUtils.getRedisUserMessage(request);
        Integer userId = userCache.getId();
        UserAddr userAddr = new UserAddr();
        BeanUtils.copyProperties(updateUserAddrDTO, userAddr);
        userAddr.setUserId(userId);

        //查询是否已有默认地址
        isDefaultAddr(updateUserAddrDTO.getDefaultAddr(), userId);

        log.info("更新用户地址");
        Integer updateNum = userAddrMapper.updateUserAddr(userAddr);
        if(updateNum == DataBasesOperationResult.ERROR){
            log.info("更新用户地址失败");
            ExceptionUtils.error(UserEnum.UPDATE_USER_ADDR_FAILED);
        }

        return Result.success();
    }

    /**
     * 判断是否有默认地址
     * @param defaultStatus 传入默认状态为1则执行更新用户默认地址
     * @param userId 用户id
     */
    public void isDefaultAddr(Short defaultStatus, Integer userId){
        //查询是否已有默认地址
        if (defaultStatus == 1){
            UserAddr userAddr1 = userAddrMapper.getDefaultAddr(userId);
            if (userAddr1 != null){
                log.info("更新用户默认地址");
                //若有则更新用户默认地址
                userAddr1.setDefaultAddr(UserAddrConstant.DEFAULT_STATE_FALSE);
                Integer updateNum = userAddrMapper.updateUserAddr(userAddr1);
                if (updateNum == DataBasesOperationResult.ERROR){
                    log.info("更新用户默认地址失败");
                    ExceptionUtils.error(UserEnum.UPDATE_USER_ADDR_FAILED);
                }
            }
        }
    }

    /**
     * 查询我的地址列表
     * @return 地址List
     */
    @Override
    public Result getUserAddList() {
        log.info("开始查询我的地址列表");
        //判断token有效性
        boolean b = redisUtils.checkTokenStatus(request);
        if(!b){
            log.info("查询地址列表失败");
            ExceptionUtils.error(WechatLoginEnum.USER_NOT_LOGIN);
        }
        //获取用户信息
        UserCache redisUserMessage = redisUtils.getRedisUserMessage(request);
        Integer userId = redisUserMessage.getId();
        //进行查询
        List<UserAddr> addrList = userAddrMapper.getUserAddrList(userId);
        log.info("查询地址列表成功");

        return Result.success(addrList);
    }


}
